package org.gitos.cloud.server.mq.logic;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.gitos.cloud.domain.comm.Constant;
import org.gitos.cloud.domain.device.Device;
import org.gitos.cloud.domain.device.Router;
import org.gitos.cloud.domain.mq.MqMsg;
import org.gitos.cloud.domain.tcp.Bucket;
import org.gitos.cloud.domain.tcp.DeviceId;
import org.gitos.cloud.server.mq.PushManager;
import org.gitos.cloud.util.HexUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;


/**
 * Created by shizhengchu on 16/3/23.
 */
public class AuthResultHandler implements Runnable {
    private static Logger log = LoggerFactory.getLogger(ApplyAuthHandler.class);

    private MqMsg msg;
    private PushManager pushManager;
    private String channleId;
    private String nodeId;
    private StringRedisTemplate stringRedisTemplate;
    private Router router;

    public AuthResultHandler(Router router) {
        this.router = router;
    }

    public Router getRouter() {
        return router;
    }

    public void setRouter(Router router) {
        this.router = router;
    }

    public MqMsg getMsg() {
        return msg;
    }

    public void setMsg(MqMsg msg) {
        this.msg = msg;
    }

    public PushManager getPushManager() {
        return pushManager;
    }

    public void setPushManager(PushManager pushManager) {
        this.pushManager = pushManager;
    }

    public String getChannleId() {
        return channleId;
    }

    public void setChannleId(String channleId) {
        this.channleId = channleId;
    }

    public String getNodeId() {
        return nodeId;
    }

    public void setNodeId(String nodeId) {
        this.nodeId = nodeId;
    }

    public StringRedisTemplate getStringRedisTemplate() {
        return stringRedisTemplate;
    }

    public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Override
    public void run() {
        byte[] OK = new byte[]{0x01};
        byte[] ERR = new byte[]{0x00};
        byte[] data2 = msg.getBucket().getContent();
        boolean result = auth(msg);
        MqMsg resultMsg = new MqMsg();
        resultMsg.setChannelId(channleId);
        resultMsg.setNodeId(nodeId);
        Bucket bucket = new Bucket();
        DeviceId deviceId = msg.getBucket().getDeviceId();
        bucket.setDeviceId(deviceId);
        if (result) {
            bucket.setContent(OK);
            bucket.setCmd(Constant.CMD_DOWN_AUTH_RESULT);
            Device device = router.fetchDevice(deviceId);
            device.setLogin(true);
            router.registerDevice(device);
        } else {
            bucket.setCmd(Constant.CMD_DOWN_CLOSE);
            bucket.setContent(ERR);
        }
        resultMsg.setBucket(bucket);
        pushManager.sendMsg(resultMsg.getNodeId(), resultMsg);
    }

    private boolean auth(MqMsg msq) {
        String data1 = stringRedisTemplate.opsForValue().get(msq.getChannelId());
        byte[] data2 = msq.getBucket().getContent();
        return f(data1, HexUtil.encodeHexStr(data2), HexUtil.encodeHexStr(msq.getBucket().getDeviceId().getValue()));
    }

    private boolean f(String data1, String data2, String mac) {
        String authCode = encode(data1, mac);
        authCode = authCode.substring(0, 16);
        return data2.equalsIgnoreCase(authCode);
    }

    public static String encode(String key, String mac) {
        log.info("key:{}, mac:{}", key, mac);
        String salt = getSalt(key, 0, 0);
        String sum = mac + salt;
        try {
            MessageDigest msgDigest = MessageDigest.getInstance("MD5");
            byte[] checksum = msgDigest.digest(sum.getBytes());
            StringBuilder sb = new StringBuilder();
            for (byte b : checksum) {
                int k = b;
                k = 0x00ff & k;
                String hex = Integer.toHexString(k);
                if (hex.length() == 1) {
                    sb.append("0");
                }
                sb.append(hex);
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            log.error("key鍔犲瘑鍑洪敊", e);
            return "";
        }

    }

    public static String getSalt(String key, int n, int length) {
        n = n % key.length();
        String curChar = "" + key.charAt(n);
        length++;
        if (length == 8) {
            return curChar;
        }
        return curChar + getSalt(key, (int) key.charAt(n), length);
    }

}
